package org.ticlib.utils
{
	import flash.net.SharedObject;
	import flash.utils.describeType;
	import flash.utils.getQualifiedClassName;
	
	/**
	 * property marked with [Config] will be saved to SharedObject
	 * handy tool for small size local configuration
	 * 
	 * note that value saved into one shared object. thus property u used for different class
	 * should not have the same name with other.
	 * 
	 * example:
	 * 
	 * class MyClass {
	 * 		[Config]
	 * 		public var myData:String;
	 * 		[Config]
	 * 		public var myDataWithDefault:int = 200;
	 * }
	 * 
	 * //to save
	 * var myClass:MyClass = new MyClass();
	 * myClass.myData = "Hello world";
	 * SimpleConfiguration.saveConfiguration(myClass);
	 * 
	 * //to load
	 * SimpleConfiguration.loadConfiguration(myClass);
	 * //myClass.myDataWithDefault -> if not set will keep its default value (200)
	 * 
	 * */
	public class SimpleConfigration
	{
		//private static const DEFAULT_CONFIG_NAME:String = "_default-config";
		private static const ANOTATION_NAME:String = "Config";
		
		private static var instance:SimpleConfigration;
		//private var defaultConfig:SharedObject;
		
		public static function getInstance():SimpleConfigration {
			if(instance == null) instance = new SimpleConfigration();
			return instance;
		}
		
		public static function clearConfiguration(model:Object):void {
			getInstance().clear(model);
		}
		
		public static function saveConfiguration(model:Object):void {
			getInstance().save(model);
		}
		
		public static function loadConfiguration(model:Object):void {
			getInstance().restore(model);
		}
		
		public function SimpleConfigration(){
			//defaultConfig = SharedObject.getLocal(DEFAULT_CONFIG_NAME);
		}
		
		public function save(model:Object):void {
			var defaultConfig:SharedObject = getSharedObject(model);
			var dsc:XML = describeType(model);
			for each(var el:Object in dsc.accessor) {
				if(el.metadata.(@name == ANOTATION_NAME).length() > 0)
					defaultConfig.data[el.@name] = model[el.@name];
			}
			for each(var vr:Object in dsc.variable) {
				if(vr.metadata.(@name == ANOTATION_NAME).length() > 0)
					defaultConfig.data[vr.@name] = model[vr.@name];
			}
		}
		
		public function clear(model:Object):void {
			var defaultConfig:SharedObject = getSharedObject(model);
			defaultConfig.clear();
		}
		
		public function restore(model:Object): void {
			var defaultConfig:SharedObject = getSharedObject(model);
			var dsc:XML = describeType(model);
			for each(var el:Object in dsc.accessor) {
				if((el.metadata.(@name == ANOTATION_NAME).length() > 0) && 
					(defaultConfig.data[el.@name] != null))
					model[el.@name] = defaultConfig.data[el.@name];
			}
			for each(var vr:Object in dsc.variable) {
				if((vr.metadata.(@name == ANOTATION_NAME).length() > 0) && 
					(defaultConfig.data[vr.@name] != null))
					model[vr.@name] = defaultConfig.data[vr.@name];
			}
		}
		
		private function getSharedObject(model:Object):SharedObject{
			var name:String = getQualifiedClassName(model).replace("::", ".");
			return SharedObject.getLocal(name);
		}
	}
}